import { ArrMethods } from "./arr";
import Dep from "./dep";

export function observer(data) {
  //1.对象的处理 vue2
  if (typeof data != "object" || data === null) {
    return data;
  }
  //创建类用来劫持
  return new Observer(data);
}
//vue2 Object.defineProperty 缺点：只能对对象里的一个属性劫持

class Observer {
  constructor(value) {
    //判断是不是数组
    if (Array.isArray(value)) {
      value.__proto__ = ArrMethods;
      this.dep = new Dep(); //给所有的对象属性添加一个dep
      //给data 定义一个属性
      Object.defineProperty(value, "__ob__", {
        enumerable: false,
        value: this,
      });
      //如果是数组对象
      this.observerArray(value);
    } else {
      this.walk(value);
    }
  }
  walk(data) {
    //{msg:'hello'}
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
      //对每个属性进行劫持
      let key = keys[i];
      let value = data[key];
      defineReactive(data, key, value);
    }
  }
  observerArray(value) {
    value.forEach((element) => {
      observer(element);
    });
  }
}
/**对对象中的数据进行劫持 */
function defineReactive(data, key, value) {
  let childDep = observer(value); //深度代理
  let dep = new Dep(); //给每一个属性添加一个dep
  // Observer.dep = dep;
  Object.defineProperty(data, key, {
    //获取值触发
    get() {
      if (Dep.target) {
        dep.depend(); //给单独的每个属性加上watcher
        if (childDep.dep) {
          //有值说明是数组类型 添加wather
          childDep.dep.depend(); //
        }
      }
      return value;
    },
    set(newvalue) {
      if (newvalue === value) return value;
      observer(newvalue);
      value = newvalue;
      dep.notify();
    },
  });
}
//当 data是数组时进行劫持
// 方法函数劫持，劫持数组方法 eg:arr.push()
